#ifndef  __CFORCER_H__        // Begin 'include-guard' block.
#define  __CFORCER_H__          // (See #endif at the very end of this file).
//==============================================================================
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_
//                               (why all the numbers? I prefer 80-column text)
//
//      CForcer.h    Force-applying object class
//
//        'forcer-vectors' in CPartSys == dyn. alloc'd arrays of CForcer objects
//                       See bottom of CPartSys.h for detailed explanation.
//==============================================================================

// multi-platform includes for the GLUT/OpenGL libraries:-----------------------
#if defined(_WIN32)
#include <GL\glew.h>    // OpenGL 'extensions wrangler' for easy access.
#include <GL\freeglut.h>// open-source GLUT functions for windows, keybd, mouse
/*---*OR*--- use:
// #include <GL/glut.h> // for 100% backwards-compatibility with Mark Kilgard's
                        // SGI-copyrighted GLUT library. Careful! this excludes
                        // freeglut's callbacks for mouse wheel, etc.
*/
/*
// freeglut.h already contains these other includes that were necessary for
// using Kilgard's original GLUT library:
#include <GL/GL.h>          // OpenGL 3D graphics rendering functions
#include <GL/Glu.h>         // OpenGL utilties functions
#include <GL/glext.h>       // #defines for all OpenGL features on your machine.
*/
#elif defined(__APPLE__)
#include <GLUT/glut.h>      // GLUT functions for windows, keybd, mouse
#include <OpenGL/GL.h>      // OpenGL 3D graphics rendering functions
#include <OpenGL/Glu.h>     // OpenGL utilties functions
#include <OpenGL/GLext.h>   // #defines for all OpenGL features on your machine.
// UNIX, Linux of all flavors;
#else
#include <unistd.h>         // defines symbolic constants, POSIX versions, etc.
#include <GL/glew.h>        // OpenGL 'extensions wrangler' for 'mesa' lib usage
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
//-----------------------------end multi-platform includes for GLUT/OpenGL-----

// C++ math, I/0 libraries (defined in the 'std' namespace)====================
#include <cmath>            // for sin, cos,...
#include <iostream>         // for cin, cout...
using namespace std;        // to access iostream's namespace

//=============================================================================
#define F_NONE      0       // Non-existent force: ignore this CForcer object
#define F_MOUSE     1       // Spring-like connection to the mouse cursor; lets
                            // you 'grab' and 'wiggle' one particle(or several).
#define F_GRAV_E    2       // Earth-gravity: pulls all particles 'downward'.
#define F_GRAV_P    3       // Planetary-gravity; all masses attract all masses.
#define F_WIND      4       // 'tornado' wind; force is fcn of 3D position
#define F_BUBBLE    5       // Constant inward force towards centerpoint if
                            // particle is > max_radius away from centerpoint.
#define F_DRAG      6       // Viscous drag -- proportional to neg. velocity.
#define F_SPRING    7       // ties together 2 particles; distance sets force
#define F_SPRINGSET 8       // a big collection of identical springs; lets you
                            // make cloth & rubbery shapes as one force-making
                            // object, instead of many many F_SPRING objects.
#define F_CHARGE    9       // attract/repel by charge and inverse distance;
                            // applies to all charged particles.
#define F_MAXKINDS  10      // 'max' is always the LAST name in our list;
                            // gives the total number of choices for forces.

class CForcer
//==============================================================================
// One force-making object; the member variable of 'forceType' selects one
// of several kinds of availabe forces.  We have member variables for *ALL*
// different kinds of forces, but we only use the subset of variables that apply
// to the current forceType.
// (FOR BETTER C++: use CForcer as a base class, and make a derived class for
//  each type of force).
// The enumerated type forceKindT permit plain-English values
// for 'forceType'.
{
    public:
    int forceType;          // sets the kind of force this object describes

    // F_GRAV_E  Earth Gravity variables........................................
    GLdouble gravConst;     // Gravitational constant: the acceleration amount
                            // in the 'down' direction
    GLdouble downDir[3];    // the 'down' direction vector.

    // F_GRAV_P  Planetary Gravity variables....................................
    // None needed--use gravConst  from Earth gravity variables.

    // F_DRAG Viscous Drag Variables............................................
    GLdouble K_drag;        // force = -velocity*K_drag.

    // F_BUBBLE Bubble-force variables:.........................................
    GLdouble bub_radius;    // bubble radius
    GLdouble bub_ctr[3];    // bubble's center point position
    GLdouble bub_force;     // inward-force's strength when outside the bubble

    // F_SPRING Single Spring variables;........................................
    int e0,e1;              // Endpoints of spring connects particle e0 to e1;
                            // (Particle e0's current x-position is:
                            //      mySys.pS0[e0].val
    GLdouble K_spring;      // Spring constant: force = stretchDistance*K_s
    GLdouble K_springdamp;  // Spring damping: (friction within the spring);
                            // force = -relVel*K_damp; 'relative velocity' is
                            // how fast the spring length is changing, and
                            // applied along the direction of the spring.

    GLdouble K_restLength;  // the zero-force length of this spring.

    // F_SPRINGSET multiple-spring variables....................................
    int *pE0, *pE1;         // Dyn. alloc'd array of spring endpoints.  These
                            // integer values select the i-th spring-connected
                            // particles from our state-vectors s0,s1,sM, etc.
    int numSprings;         // the number of springs in the array.
    // NOTE: all springs in the spring-set use the same K_spring and K_restLength,
    void makeSpringSet(int size);   // dyn. alloc. a set of springs
    void wipeSpringSet(void);        // destroy any existing dyn. alloc'd springs


    CForcer(void);          // default constructor/destructor
    ~CForcer(void);
};

#endif //end of #ifndef  __CFORCER_H__ include guard
